<template>
	<span class="check-photo-close iconfont icon-wx-close-thin" v-if="closeBtn"></span>
	<div class="swipe">
		<div class="swipe-items-wrap" v-el:wrap>
			<slot></slot>
		</div>
		<div class="swipe-indicators" v-show="showIndicators">
			<div class="swipe-indicator" v-for="page in pages" :class="{ active: $index === index }"></div>
		</div>
	</div>


	<!--
			<div class="page-swipe">
				<swipe class="my-swipe">
					<swipe-item class="slide1">Slide1</swipe-item>
					<swipe-item class="slide2">Slide2</swipe-item>
					<swipe-item class="slide3">Slide3</swipe-item>
				</swipe>
				<swipe class="my-swipe" :auto="0">
					<swipe-item class="slide1">Slide1</swipe-item>
					<swipe-item class="slide2">Slide2</swipe-item>
					<swipe-item class="slide3">Slide3</swipe-item>
				</swipe>

				<br>

				<swipe class="my-swipe" :speed="900" :auto="0" :show-indicators="false">
					<swipe-item class="slide1">SINGLE SLIDE</swipe-item>
				</swipe>

				<br>

				<swipe class="my-swipe" :speed="900" :auto="0" :show-indicators="false" :no-drag="true">
					<swipe-item class="slide1">SINGLE SLIDE</swipe-item>
				</swipe>
			</div>-->
</template>
<script>
	import { once, addClass, removeClass } from 'wind-dom';

	export default {
		name: 'mt-swipe',

		created() {
			this.dragState = {};
		},

		data() {
			return {
				ready: false,
				dragging: false,
				userScrolling: false,
				animating: false,
				index: 0,
				pages: [],
				timer: null,
				reInitTimer: null,
				noDrag: false
			};
		},

		props: {
			speed: {
				type: Number,
				default: 300
			},

			auto: {
				type: Number,
				default: 3000
			},

			closeBtn: {
				type: Boolean,
				default: false
			},

			continuous: {
				type: Boolean,
				default: true
			},

			showIndicators: {
				type: Boolean,
				default: true
			},

			noDragWhenSingle: {
				type: Boolean,
				default: true
			},

			prevent: {
				type: Boolean,
				default: false
			}
		},

		events: {
			swipeItemCreated() {
				if (!this.ready) return;

				clearTimeout(this.reInitTimer);
				this.reInitTimer = setTimeout(() => {
					this.reInitPages();
				}, 100);
			},

			swipeItemDestroyed(){
				if (!this.ready) return;

				clearTimeout(this.reInitTimer);
				this.reInitTimer = setTimeout(() => {
					this.reInitPages();
				}, 100);
			}
		},

		methods: {
			translate(element, offset, speed, callback) {
				if (speed) {
					this.animating = true;
					element.style.webkitTransition = '-webkit-transform ' + speed + 'ms ease-in-out';
					setTimeout(() => element.style.webkitTransform = `translate3d(${offset}px, 0, 0)`, 50);

					var called = false;

					var transitionEndCallback = () => {
						if (called) return;
						called = true;
						this.animating = false;
						element.style.webkitTransition = '';
						element.style.webkitTransform = '';
						if (callback) {
							callback.apply(this, arguments);
						}
					};

					once(element, 'webkitTransitionEnd', transitionEndCallback);
					setTimeout(transitionEndCallback, speed + 100); // webkitTransitionEnd maybe not fire on lower version android.
				} else {
					element.style.webkitTransition = '';
					element.style.webkitTransform = `translate3d(${offset}px, 0, 0)`;
				}
			},

			reInitPages() {
				var children = this.$children;
				this.noDrag = children.length === 1 && this.noDragWhenSingle;

				var pages = [];
				this.index = 0;

				children.forEach(function(child, index) {
					pages.push(child.$el);

					removeClass(child.$el, 'active');

					if (index === 0) {
						addClass(child.$el, 'active');
					}
				});

				this.pages = pages;
			},

			doAnimate(towards, options) {
				if (this.$children.length === 0) return;
				if (!options && this.$children.length < 2) return;

				var prevPage, nextPage, currentPage, pageWidth, offsetLeft;
				var speed = this.speed || 300;
				var index = this.index;
				var pages = this.pages;
				var pageCount = pages.length;

				if (!options) {
					pageWidth = this.$el.clientWidth;
					currentPage = pages[index];
					prevPage = pages[index - 1];
					nextPage = pages[index + 1];
					if (this.continuous && pages.length > 1) {
						if (!prevPage) {
							prevPage = pages[pages.length - 1];
						}
						if (!nextPage) {
							nextPage = pages[0];
						}
					}
					if (prevPage) {
						prevPage.style.display = 'block';
						this.translate(prevPage, -pageWidth);
					}
					if (nextPage) {
						nextPage.style.display = 'block';
						this.translate(nextPage, pageWidth);
					}
				} else {
					prevPage = options.prevPage;
					currentPage = options.currentPage;
					nextPage = options.nextPage;
					pageWidth = options.pageWidth;
					offsetLeft = options.offsetLeft;
				}

				var newIndex;

				var oldPage = this.$children[index].$el;

				if (towards === 'prev') {
					if (index > 0) {
						newIndex = index - 1;
					}
					if (this.continuous && index === 0) {
						newIndex = pageCount - 1;
					}
				} else if (towards === 'next') {
					if (index < pageCount - 1) {
						newIndex = index + 1;
					}
					if (this.continuous && index === pageCount - 1) {
						newIndex = 0;
					}
				}

				var callback = () => {
					if (newIndex !== undefined) {
						var newPage = this.$children[newIndex].$el;
						removeClass(oldPage, 'active');
						addClass(newPage, 'active');

						this.index = newIndex;
					}

					if (prevPage) {
						prevPage.style.display = '';
					}

					if (nextPage) {
						nextPage.style.display = '';
					}
				};

				setTimeout(() => {
					if (towards === 'next') {
						this.translate(currentPage, -pageWidth, speed, callback);
						if (nextPage) {
							this.translate(nextPage, 0, speed);
						}
					} else if (towards === 'prev') {
						this.translate(currentPage, pageWidth, speed, callback);
						if (prevPage) {
							this.translate(prevPage, 0, speed);
						}
					} else {
						this.translate(currentPage, 0, speed, callback);
						if (typeof offsetLeft !== 'undefined') {
							if (prevPage && offsetLeft > 0) {
								this.translate(prevPage, pageWidth * -1, speed);
							}
							if (nextPage && offsetLeft < 0) {
								this.translate(nextPage, pageWidth, speed);
							}
						} else {
							if (prevPage) {
								this.translate(prevPage, pageWidth * -1, speed);
							}
							if (nextPage) {
								this.translate(nextPage, pageWidth, speed);
							}
						}
					}
				}, 10);
			},

			next() {
				this.doAnimate('next');
			},

			prev() {
				this.doAnimate('prev');
			},

			doOnTouchStart: function(event) {
				if (this.noDrag) return;

				var element = this.$el;
				var dragState = this.dragState;
				var touch = event.touches[0];

				dragState.startTime = new Date();
				dragState.startLeft = touch.pageX;
				dragState.startTop = touch.pageY;
				dragState.startTopAbsolute = touch.clientY;

				dragState.pageWidth = element.offsetWidth;
				dragState.pageHeight = element.offsetHeight;

				var prevPage = this.$children[this.index - 1];
				var dragPage = this.$children[this.index];
				var nextPage = this.$children[this.index + 1];

				if (this.continuous && this.pages.length > 1) {
					if (!prevPage) {
						prevPage = this.$children[this.$children.length - 1];
					}
					if (!nextPage) {
						nextPage = this.$children[0];
					}
				}

				dragState.prevPage = prevPage ? prevPage.$el : null;
				dragState.dragPage = dragPage ? dragPage.$el : null;
				dragState.nextPage = nextPage ? nextPage.$el : null;

				if (dragState.prevPage) {
					dragState.prevPage.style.display = 'block';
				}

				if (dragState.nextPage) {
					dragState.nextPage.style.display = 'block';
				}
			},

			doOnTouchMove: function(event) {
				if (this.noDrag) return;

				var dragState = this.dragState;
				var touch = event.touches[0];

				dragState.currentLeft = touch.pageX;
				dragState.currentTop = touch.pageY;
				dragState.currentTopAbsolute = touch.clientY;

				var offsetLeft = dragState.currentLeft - dragState.startLeft;
				var offsetTop = dragState.currentTopAbsolute - dragState.startTopAbsolute;

				var distanceX = Math.abs(offsetLeft);
				var distanceY = Math.abs(offsetTop);
				if (distanceX < 5 || (distanceX >= 5 && distanceY >= 1.73 * distanceX)) {
					this.userScrolling = true;
					return;
				} else {
					this.userScrolling = false;
					event.preventDefault();
				}
				offsetLeft = Math.min(Math.max(-dragState.pageWidth + 1, offsetLeft), dragState.pageWidth - 1);

				var towards = offsetLeft < 0 ? 'next' : 'prev';

				if (dragState.prevPage && towards === 'prev') {
					this.translate(dragState.prevPage, offsetLeft - dragState.pageWidth);
				}
				this.translate(dragState.dragPage, offsetLeft);
				if (dragState.nextPage && towards === 'next') {
					this.translate(dragState.nextPage, offsetLeft + dragState.pageWidth);
				}
			},

			doOnTouchEnd: function() {
				if (this.noDrag) return;

				var dragState = this.dragState;

				var dragDuration = new Date() - dragState.startTime;
				var towards = null;

				var offsetLeft = dragState.currentLeft - dragState.startLeft;
				var offsetTop = dragState.currentTop - dragState.startTop;
				var pageWidth = dragState.pageWidth;
				var index = this.index;
				var pageCount = this.pages.length;

				if (dragDuration < 300) {
					let fireTap = Math.abs(offsetLeft) < 5 && Math.abs(offsetTop) < 5;
					if (isNaN(offsetLeft) || isNaN(offsetTop)) {
						fireTap = true;
					}
					if (fireTap) {
						this.$children[this.index].$emit('tap');
					}
				}

				if (dragDuration < 300 && dragState.currentLeft === undefined) return;

				if (dragDuration < 300 || Math.abs(offsetLeft) > pageWidth / 2) {
					towards = offsetLeft < 0 ? 'next' : 'prev';
				}

				if (!this.continuous) {
					if ((index === 0 && towards === 'prev') || (index === pageCount - 1 && towards === 'next')) {
						towards = null;
					}
				}

				if (this.$children.length < 2) {
					towards = null;
				}

				this.doAnimate(towards, {
					offsetLeft: offsetLeft,
					pageWidth: dragState.pageWidth,
					prevPage: dragState.prevPage,
					currentPage: dragState.dragPage,
					nextPage: dragState.nextPage
				});

				this.dragState = {};
			}
		},

		destroyed() {
			if (this.timer) {
				clearInterval(this.timer);
				this.timer = null;
			}
			if (this.reInitTimer) {
				clearTimeout(this.reInitTimer);
				this.reInitTimer = null;
			}
		},

		ready() {
			this.ready = true;

			if (this.auto > 0) {
				this.timer = setInterval(() => {
					if (!this.dragging && !this.animating) {
						this.next();
					}
				}, this.auto);
			}

			this.reInitPages();

			var element = this.$el;

			element.addEventListener('touchstart', (event) => {
				if (this.prevent) {
					event.preventDefault();
				}
				if (this.animating) return;
				this.dragging = true;
				this.userScrolling = false;
				this.doOnTouchStart(event);
			});

			element.addEventListener('touchmove', (event) => {
				if (!this.dragging) return;
				this.doOnTouchMove(event);
			});

			element.addEventListener('touchend', (event) => {
				if (this.userScrolling) {
					this.dragging = false;
					this.dragState = {};
					return;
				}
				if (!this.dragging) return;
				this.doOnTouchEnd(event);
				this.dragging = false;
			});
		}
	};
</script>

<style>
	.check-photo-box{position:fixed;top: 0;bottom: 0;left: 0;right: 0;z-index: 10;width: 100%;height: 100%;background-color:#000;padding-top: 45px;}
	.check-photo-box .swipe{height: 100%;padding: 0 10px;}
	.check-photo-box .swipe img{height: auto;width: auto;max-height: 100%;max-width: 100%;}
	.check-photo-close,.check-photo-num{color: #fff;position: absolute;top: 15px;font-size: 16px;}
	.check-photo-num{left: 20px;}
	.check-photo-close{right: 20px;}

	.swipe {
		overflow: hidden;
		position: relative;
	}
	.swipe-items-wrap {
		position: relative;
		overflow: hidden;
		height: 100%;
	}
	.swipe-items-wrap > div {
		position: absolute;
		transform: translateX(-100%);
		width: 100%;
		height: 100%;
		display: none;
	}
	.swipe-items-wrap > div.active {
		display: block;
		transform: none;
	}
	.swipe-indicators {
		position: absolute;
		bottom: 10px;
		left: 50%;
		transform: translateX(-50%);
	}
	.swipe-indicator {
		width: 8px;
		height: 8px;
		display: inline-block;
		border-radius: 100%;
		background: #000;
		opacity: 0.2;
		margin: 0 3px;
	}
	.swipe-indicator.active {
		background: #fff;
	}
</style>